import json
import logging
import re

from django.http import JsonResponse
from django.views import View
from django.core.cache import caches
from django.contrib.auth import logout

from apps.areas.models import Area
from apps.users.models import Address
from utils.views import LoginRequiredJSONMixin


class AreaView(View):
    def get(self, request):
        # 1. 查询省份信息
        provinces = Area.objects.filter(parent__isnull=True)
        provinces = [{'id': i.id, 'name': i.name} for i in provinces]
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'province_list': provinces})


# 市区县的展现
class SubareaView(LoginRequiredJSONMixin, View):
    def get(self, request, id):
        # 1. 获取省份id, 市区的id, 查询信息
        # 2. 將对象转换为字典数据
        # 返回相应
        # 找到省份
        areas_cache = caches['areas']
        # 先查寻缓存数据
        data = areas_cache.get('province_%s' % id)
        # 缓存中没有数据则查询并缓存数据
        if data is None:
            try:
                up_level = Area.objects.get(id=id)
            except Exception as e:
                logger = logging.getLogger('logger')
                logger.error(e)
                return JsonResponse({'code': 400, 'errmsg': '省份id错误'})
            # 省份对应的市区县
            down_level = up_level.subs.all()
            # 保存缓存数据
            data = [{"name": i.name, 'id': i.id} for i in down_level]

            # cache.set(key, value, expire, cache='')
            areas_cache.set('province_%s' % id, data, timeout=24 * 3600)

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'sub_data': {'subs': data}})


#  举例：   美多商城
#  注册用户一个忆
#  日活用户 1%   一百万
#  下单比例 1%   1w
#  新增地址的概率 %1  100 300次
#  针对一些不经常变化的数据， 我们最好缓存到redis(内容）中减少数据库的查询


"""
需求：
    新增地址
前端：
    用户填写完毕后，发送ajex请求，会携带相关信息
后端：
    请求：      接受请求， 获取参数
    业务逻辑：   数据入库
    响应：      返回响应
"""


class AddressCreateView(LoginRequiredJSONMixin, View):
    def post(self, request):
        user = request.user
        count = user.addresses.all().filter(is_deleted=0).count()
        if count >= 20:
            return JsonResponse({'code': 400, 'errmsg': "超过地址数量"})
        json_str = request.body.decode()
        data = json.loads(json_str)
        # 获取json数据
        province_id = data.get('province_id')
        receiver = data.get('receiver')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        tel = data.get('tel')
        email = data.get('email')

        title = data.get('title')

        # 验证参数
        # 2.1 验证必传参数
        # 2.2 省市区是否正确
        # 2.3 手机号
        # 2.4 地址
        # 2.5 收货人， 详细地址长度验证
        # 2.6 邮箱
        # 2.7 固定时间

        # 3. 数据入库
        # 4. 反回响应

        if not all([province_id, receiver, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        try:
            province = Area.objects.get(id=province_id)
            city = province.subs.get(id=city_id)
            district = city.subs.get(id=district_id)
        except Exception as e:
            logger = logging.getLogger('logger')
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': "地址有误"})
        if re.match("^1[35678]\d{9}$", mobile) is None:
            return JsonResponse({'code': 400, 'errmsg': '手机号不符合规范'})
        if re.match('^.{1,20}$', receiver) is None:
            return JsonResponse({'code': 400, 'errmsg': '收件人名字不合合规范'})
        if re.match("^.{1,50}$", place) is None:
            return JsonResponse({'code': 400, 'errmsg': '详细地址不符合规范'})
        if email != '' and re.match('[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}', email) is None:
            return JsonResponse({'code': 400, 'errmsg': '邮箱格式错误'})
        if tel != '' and re.match('^(\+\d{1,3}[- ]?)?\(?\d{3}\)?[- ]?\d{3}[- ]?\d{4}$', tel) is None:
            return JsonResponse({'code': 0, 'errmsg': '固定电话格式错误'})

        if title == '':
            title = receiver
        address = Address.objects.create(user=user, title=title, receiver=receiver, city_id=city_id,
                                         district_id=district_id, place=place, mobile=mobile, tel=tel, email=email,
                                         province_id=province_id)
        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
            'province': address.province.name,
            'distinct': address.district.name,
            'city': address.city.name
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict})


class AddressView(LoginRequiredJSONMixin, View):
    def get(self, request):
        # 查询指定数据
        # 將对象数据转换为字符串
        # 返回响应
        user = request.user
        addresses = Address.objects.filter(user=user, is_deleted=False)
        addresses_list = [
            {
                "id": i.id,
                "title": i.title,
                "province": i.province.name,
                "receiver": i.receiver,
                "city": i.city.name,
                "district": i.district.name,
                "place": i.place,
                "mobile": i.mobile,
                'tel':  i.tel,
                'email': i.email
            }for i in addresses]
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'addresses': addresses_list} )


class AddressTitleView(LoginRequiredJSONMixin, View):
    def put(self, request, id):
        json_data = request.body.decode()
        data = json.loads(json_data)
        title = data.get('title')
        if title is None or title == '':
            return JsonResponse({'code': 400, 'errmsg': "请输入要修改的title名称"})

        # 先查后改
        address = request.user.addresses.get(id=id)
        address.title = title
        address.save()
        return JsonResponse({'code': 0, 'essmsg': "修改成功"})


# 修改地址类视图
class AlterAddressView(LoginRequiredJSONMixin, View):
    def put(self, request, id):
        # 从json中取得数据
        json_data = request.body.decode()
        data = json.loads(json_data)

        title = data.get('title')
        province = data.get('province')
        receiver = data.get('receiver')
        city = data.get('city')
        district = data.get('district')
        place = data.get('place')
        mobile = data.get('mobile')
        tel = data.get('til')
        email = data.get('email')
        province_id = data.get("province_id")
        city_id = data.get("city_id")
        district_id = data.get('district_id')

        # 先查后改
        address = request.user.addresses.get(id=id)

        if not all([province_id, receiver, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        # 验证数据
        if re.match("^1[35678]\d{9}$", mobile) is None:
            return JsonResponse({'code': 400, 'errmsg': '手机号不符合规范'})
        if re.match('^.{1,20}$', receiver) is None:
            return JsonResponse({'code': 400, 'errmsg': '收件人名字不合合规范'})
        if re.match("^.{1,50}$", place) is None:
            return JsonResponse({'code': 400, 'errmsg': '详细地址不符合规范'})
        if email != '' and re.match('[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}', email) is None:
            return JsonResponse({'code': 400, 'errmsg': '邮箱格式错误'})
        if tel is not None and re.match('^(\+\d{1,3}[- ]?)?\(?\d{3}\)?[- ]?\d{3}[- ]?\d{4}$', tel) is None:
            return JsonResponse({'code': 0, 'errmsg': '固定电话格式错误'})

        address.title = title
        address.mobile = mobile
        address.receiver = receiver
        address.province_id = province_id
        address.city_id = city_id
        address.district_id = district_id
        address.place = place
        address.mobile = mobile
        address.tel = tel
        address.email = email
        address.save()
        return JsonResponse({'code': 0, 'errmsg': 'ok'})
    def delete(self, requset, id):
        # 先查后改
        address = requset.user.addresses.get(id=id)
        address.is_deleted = True
        address.save()
        return JsonResponse({'code': 0, 'errmsg': "ok"})




